#!/usr/bin/env python
# coding: utf-8

# In[1]:


import numpy as np
def handle_price_data(instrument, lookforwardperiod, flag):
    # 获取日级别数据，并进行简单处理，聚宽的API文档
    data = get_price(instrument, '2017-01-03', '2019-04-15', 'daily')
    n = len(data)    
    data = data[~np.isnan(data['open'])] # ~为否定，不是空值返回1
    if n == len(data) and flag == 1: # 训练集:
        data = get_price(instrument, '2017-01-03', '2018-09-28', 'daily')
    elif n == len(data) and flag == 2: # 测试集:
        data = get_price(instrument, '2018-10-08', '2019-04-15', 'daily')
    elif n != len(data) and flag == 1:
        data = data.iloc[:int(len(data) * 0.78)]
    elif n != len(data) and flag == 2:
        data = data.iloc[int(len(data) * 0.78):]   
    data_close = np.array(data.close)
    data_open = np.array(data.open)
    data_high = np.array(data.high)
    data_low = np.array(data.low)
    data_volume = np.array(data.volume)
    
    # 找到价格的最高点和最低点，定义为最高价>=未来5天（参数为lookforwardperiod）的最高价
    price_list = np.zeros(len(data))
    for t in range(0, len(data)):
        if data_high[t] == max(data_high[t:t+lookforwardperiod]):
            price_list[t] = 1
        elif data_low[t] == min(data_low[t:t+lookforwardperiod]):
            price_list[t] = -1
    return data, data_close, data_open, data_high, data_low, data_volume, price_list

def test_for_price_difference(tindex, data_close, data_high, data_low, price_list, lookbackperiod):
    # 输入的技术指标为tindex
    tindex = np.nan_to_num(tindex) # 用0填充nan
    # 记录前高和前低的数组，初始化为inf和-inf
    prev_high = np.full((len(data_close), 1), np.inf) # 前高
    # np.full(x, y) 造一个数组，形状是x，填充值是y;np.inf正无穷
    prev_low = np.full((len(data_close), 1), -np.inf) # 前低
    open_high = [] # 高点开仓价
    open_low = [] # 低点开仓价
    close_high = [] # 高点平仓价
    close_low = [] # 低点平仓价
    pos = np.zeros(len(data_close)) # 记录仓位，防止连续突破导致的连续开仓
    close_time = np.inf # 记录平仓位置
    for t in range(lookbackperiod*2, len(data_close)-lookbackperiod):
        # 首先更新前高和前低
        prev_high[t] = prev_high[t-1]
        prev_low[t] = prev_low[t-1]
        # 如果出现局部最高或最低点，则更新前高和前低
        if tindex[t-lookbackperiod+1] == max(tindex[t-lookbackperiod+1:t+1]) and tindex[t-lookbackperiod+1] == max(tindex[t-lookbackperiod*2+2:t-lookbackperiod+2]):
            prev_high[t] = tindex[t-lookbackperiod+1]
        elif tindex[t-lookbackperiod+1] == min(tindex[t-lookbackperiod+1:t+1]) and tindex[t-lookbackperiod+1] == min(tindex[t-lookbackperiod*2+2:t-lookbackperiod+2]):
            prev_low[t] = tindex[t-lookbackperiod+1]

        # 判断是否突破前高或前低
        if tindex[t] > prev_high[t] and pos[t] < 1: # 突破前高
            open_high = np.append(open_high, data_close[t]) # 开仓价格是当天的收盘价
            # 找到之后的最高价，为price_list中从t+1开始第一个为1的位置
            close_time = next((x for x in range(t+1,len(price_list)) if price_list[x] == 1), len(data_close)-1)
            close_high = np.append(close_high,data_high[close_time])
            # 更新仓位
            pos[t+1] = 1
        elif tindex[t] < prev_low[t] and pos[t] > -1: # 突破前低
            open_low = np.append(open_low, data_close[t]) 
            close_time = next((x for x in range(t+1,len(price_list)) if price_list[x] == -1), len(data_close)-1)
            close_low = np.append(close_low,data_low[close_time])
            pos[t+1] = -1
        else: # 如果没有突破，仓位保持
            pos[t+1] = pos[t]
        if t == close_time+1: # 时间过了平仓时间之后，将仓位重置为0，使得可以继续开仓
            pos[t+1] = 0
            close_time = np.inf
    #print (np.mean(close_high-open_high), np.mean(open_low-close_low))
    return open_high,close_high,open_low,close_low

def test_sample_high(tindex, data_close, data_high, data_low, price_list, lookforwardperiod, result):
    open_high,close_high,open_low,close_low = test_for_price_difference(tindex, data_close, data_high, data_low, price_list, lookforwardperiod)
    if len(open_high) == 0:
        result = vstack((result,np.array([0, 0])))
    else:
        result = vstack((result,np.array([np.mean(close_high-open_high), np.mean(close_high/open_high-1)])))
    return result

def test_sample_low(tindex, data_close, data_high, data_low, price_list, lookforwardperiod, result):
    open_high,close_high,open_low,close_low = test_for_price_difference(tindex, data_close, data_high, data_low, price_list, lookforwardperiod)
    if len(open_low) == 0:
        result = vstack((result,np.array([0, 0])))
    else:
        result = vstack((result,np.array([np.mean(open_low-close_low), np.mean(open_low/close_low-1)])))
    return result


# In[2]:


a = np.array([1, 2, 3])
b = np.array([2, 3, 4]) 
vstack((a,b))


# In[4]:


np.mean([1,2,2])


# In[2]:


import talib
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

L = ['SC8888.XINE', 'AG8888.XSGE', 'AL8888.XSGE', 'AU8888.XSGE', 'BU8888.XSGE', 'CU8888.XSGE', 'FU8888.XSGE',
    'HC8888.XSGE', 'NI8888.XSGE', 'PB8888.XSGE', 'RB8888.XSGE', 'RU8888.XSGE', 'SN8888.XSGE', 'ZN8888.XSGE',
    'SP8888.XSGE', 'AP8888.XZCE', 'CF8888.XZCE', 'FG8888.XZCE', 'MA8888.XZCE', 'OI8888.XZCE', 'RM8888.XZCE',
    'SF8888.XZCE', 'SM8888.XZCE', 'SR8888.XZCE', 'TA8888.XZCE', 'ZC8888.XZCE', 'A8888.XDCE', 'B8888.XDCE',
    'C8888.XDCE', 'CS8888.XDCE', 'I8888.XDCE', 'J8888.XDCE', 'JD8888.XDCE', 'JM8888.XDCE', 'L8888.XDCE',
    'M8888.XDCE', 'P8888.XDCE', 'PP8888.XDCE', 'V8888.XDCE', 'Y8888.XDCE', 'EG8888.XDCE']
lookforwardperiod = 5
lookbackperiod = 5

def data_to_price(data):
    data_close = np.array(data.close)
    data_open = np.array(data.open)
    data_high = np.array(data.high)
    data_low = np.array(data.low)
    data_vol = np.array(data.volume)
    return data_close, data_open, data_high, data_low, data_vol


# In[ ]:


def RSI(data, n):
    close,openp,high,low,vol = data_to_price(data)
    return talib.RSI(close, n)

def WR(data, n):
    close,openp,high,low,vol = data_to_price(data)
    return talib.WILLR(high, low, close, n)

def ROC(data, n):
    close,openp,high,low,vol = data_to_price(data)
    return talib.ROC(close, n)

def ATR(data, n):
    close,openp,high,low,vol = data_to_price(data)
    return talib.ATR(high, low, close, n)

def CCI(data, n):
    close,openp,high,low,vol = data_to_price(data)
    return talib.CCI(high, low, close, n)

def MTM(data, n):
    close,openp,high,low,vol = data_to_price(data)
    return close - np.roll(close, n)

def BIAS(data, n):
    close,openp,high,low,vol = data_to_price(data)
    return (data_close - talib.SMA(data_close,n))/talib.SMA(data_close,n)*100

def DMI_ADX(data, n):
    close,openp,high,low,vol = data_to_price(data)
    return talib.ADX(high, low, close, n)

def DMI_ADXR(data, n):
    close,openp,high,low,vol = data_to_price(data)
    return talib.ADXR(high, low, close, n)

def PSY(data, n):
    close,openp,high,low,vol = data_to_price(data)
    tmp = ((np.array([0]+list(np.diff(close))))>0) * 1.0
    return np.nan_to_num(talib.SMA(tmp,n)*100)

def RC(data, n):
    close,openp,high,low,vol = data_to_price(data)
    rc = np.nan_to_num(close / np.roll(close, n))
    return rc

def RC_ARC(data, n):
    close,openp,high,low,vol = data_to_price(data)
    rc = np.nan_to_num(close / np.roll(close, n))
    arc = talib.SMA(np.roll(rc, 1), n)
    return arc

def ARBR_AR(data, n):
    close,openp,high,low,vol = data_to_price(data)
    return talib.SMA(high-openp, n) / talib.SMA(openp-low, n) * 100 

def ARBR_BR(data, n):
    close,openp,high,low,vol = data_to_price(data)
    return talib.SMA(np.maximum(0,high-np.roll(close,1)),n) / talib.SMA(np.maximum(0,np.roll(close,1)-low),n) * 100
    
def ADTM(data, n):
    close,openp,high,low,vol = data_to_price(data)
    dtm = np.zeros(len(openp))
    dbm = np.zeros(len(openp))
    adtm = np.zeros(len(openp))
    for t in range(1, len(openp)):
        if openp[t] <= openp[t-1]:
            dtm[t] = 0
        else:
            dtm[t] = np.maximum(high[t]-openp[t],openp[t]-openp[t-1])
        if openp[t] >= openp[t-1]:
            dbm[t] = 0
        else:
            dbm[t] = np.maximum(openp[t]-low[t],openp[t]-openp[t-1])
    stm = talib.SMA(dtm, n)
    sbm = talib.SMA(dbm, n)
    for t in range(1, len(openp)):
        if stm[t] > sbm[t]:
            adtm[t] = (stm[t] - sbm[t]) / stm[t]
        elif stm[t] == sbm[t]:
            adtm[t] = 0
        else:
            adtm[t] = (stm[t] - sbm[t]) / sbm[t]
    return adtm

def DDI(data, n):
    close,openp,high,low,vol = data_to_price(data)
    tr = np.maximum(np.abs(high - np.roll(high, 1)), np.abs(low - np.roll(low, 1)))
    dmz = np.zeros(len(high))
    dmf = np.zeros(len(high))
    for t in range(1, len(high)):
        if high[t] + low[t] <= high[t-1] + low[t-1]:
            dmz[t] = 0
        else:
            dmz[t] = max(np.abs(high[t]-high[t-1]), np.abs(low[t]-low[t-1]))
        if high[t] + low[t] >= high[t-1] + low[t-1]:
            dmf[t] = 0
        else:
            dmf[t] = max(np.abs(high[t]-high[t-1]), np.abs(low[t]-low[t-1]))
    diz = talib.SMA(dmz,n) / (talib.SMA(dmz,n) + talib.SMA(dmf,n))   
    dif = talib.SMA(dmf,n) / (talib.SMA(dmz,n) + talib.SMA(dmf,n))  
    ddi = diz - dif
    return ddi

def MI_A(data, n):
    close,openp,high,low,vol = data_to_price(data)
    return close - np.roll(close, n)

def MI(data, n):
    close,openp,high,low,vol = data_to_price(data)
    a = close - np.roll(close, n)
    mi = np.zeros(len(close))
    for t in range(0,len(close)):
        mi[t] = mi[t-1]*(n-1)/n + a[t]*1/n
    return mi

def SRDM(data, n):
    close,openp,high,low,vol = data_to_price(data)
    dmz = np.zeros(len(high))
    dmf = np.zeros(len(high))
    for t in range(1, len(high)):
        if high[t] + low[t] <= high[t-1] + low[t-1]:
            dmz[t] = 0
        else:
            dmz[t] = max(np.abs(high[t]-high[t-1]), np.abs(low[t]-low[t-1]))
        if high[t] + low[t] >= high[t-1] + low[t-1]:
            dmf[t] = 0
        else:
            dmf[t] = max(np.abs(high[t]-high[t-1]), np.abs(low[t]-low[t-1]))
    admz = talib.SMA(dmz, 10)
    admf = talib.SMA(dmf, 10)
    srdm = np.zeros(len(high))
    for t in range(1, len(high)):
        if admz[t] > admf[t]:
            srdm[t] = (admz[t] - admf[t]) / admz[t]
        elif admz[t] == admf[t]:
            srdm[t] = 0
        else:
            srdm[t] = (admz[t] - admf[t]) / admf[t]
    return np.nan_to_num(srdm)

def SRDM_ASRDM(data, n):
    close,openp,high,low,vol = data_to_price(data)
    dmz = np.zeros(len(high))
    dmf = np.zeros(len(high))
    for t in range(1, len(high)):
        if high[t] + low[t] <= high[t-1] + low[t-1]:
            dmz[t] = 0
        else:
            dmz[t] = max(np.abs(high[t]-high[t-1]), np.abs(low[t]-low[t-1]))
        if high[t] + low[t] >= high[t-1] + low[t-1]:
            dmf[t] = 0
        else:
            dmf[t] = max(np.abs(high[t]-high[t-1]), np.abs(low[t]-low[t-1]))
    admz = talib.SMA(dmz, 10)
    admf = talib.SMA(dmf, 10)
    srdm = np.zeros(len(high))
    for t in range(1, len(high)):
        if admz[t] > admf[t]:
            srdm[t] = (admz[t] - admf[t]) / admz[t]
        elif admz[t] == admf[t]:
            srdm[t] = 0
        else:
            srdm[t] = (admz[t] - admf[t]) / admf[t]
    srdm = np.nan_to_num(srdm)
    asrdm = np.zeros(len(high))
    for t in range(0,len(high)):
        asrdm[t] = asrdm[t-1]*(n-1)/n + srdm[t]*1/n
    return asrdm

def CR(data, n):
    close,openp,high,low,vol = data_to_price(data)
    mid = (high + low + close)/3
    cr = talib.SMA(np.maximum(0, high-np.roll(mid,1)),n) / talib.SMA(np.maximum(0, np.roll(mid,1)-low),n) * 100
    return np.nan_to_num(cr)

method = ['相对强弱指标-rsi','威廉指标-wr','变动速率-roc','真实波幅-atr','顺势指标-cci','动力指标-mtm',         '乖离率-bias','趋向指标dmi-adx','趋向指标dmi-adxr','心理线-psy','变化率指数-rc','变化率指数-arc',         '人气意愿指标-arbr-ar','人气意愿指标-arbr-br','动态买卖气指标-adtm','方向标准离差指数-ddi',         '动量指标-mi-a','动量指标-mi','动向速度比率-srdm','动向速度比率-asrdm','CR能量指标-cr']
methoddict = {'相对强弱指标-rsi':RSI,'威廉指标-wr':WR,'变动速率-roc':ROC,'真实波幅-atr':ATR,'顺势指标-cci':CCI,              '动力指标-mtm':MTM,'乖离率-bias':BIAS,'趋向指标dmi-adx':DMI_ADX,'趋向指标dmi-adxr':DMI_ADXR,              '心理线-psy':PSY,'变化率指数-rc':RC,'变化率指数-arc':RC_ARC,'人气意愿指标-arbr-ar':ARBR_AR,              '人气意愿指标-arbr-br':ARBR_BR,'动态买卖气指标-adtm':ADTM,'方向标准离差指数-ddi':DDI,              '动量指标-mi-a':MI_A,'动量指标-mi':MI,'动向速度比率-srdm':SRDM,'动向速度比率-asrdm':SRDM_ASRDM,              'CR能量指标-cr':CR}

for tmpmtd in method:
    print(tmpmtd)    
    result_high = pd.DataFrame(index = L, columns = ['n', 'absdiff', 'reldiff'])
    result_low = pd.DataFrame(index = L, columns = ['n', 'absdiff', 'reldiff'])
    colomnnum = result_high.shape[1]
    testresult1 = np.empty((0,2), float)
    testresult2 = np.empty((0,2), float)
    for instrument in L:
        data, data_close,data_open,data_high,data_low,data_volume,price_list=handle_price_data(instrument,lookforwardperiod,1)
        highresult = np.empty((0,colomnnum), float)
        lowresult = np.empty((0,colomnnum), float)    
        for n in range(2,100,1):
            indicator = methoddict[tmpmtd](data, n) # 计算技术指标
            open_high,close_high,open_low,close_low = test_for_price_difference(indicator, data_close, data_high, data_low, price_list, lookbackperiod)
            if len(open_high) != 0:
                highresult = vstack((highresult,np.array([n, np.mean(close_high-open_high), np.mean(close_high/open_high-1)])))
            if len(open_low) != 0:
                lowresult = vstack((lowresult,np.array([n, np.mean(open_low-close_low), np.mean(open_low/close_low-1)])))
        if len(lowresult) != 0:
            result_low.loc[instrument] = lowresult[np.where(lowresult[:,colomnnum-1] == np.amin(lowresult[:,colomnnum-1]))[0][0],:]
        if len(highresult) != 0:
            result_high.loc[instrument] = highresult[np.where(highresult[:,colomnnum-1] == np.amin(highresult[:,colomnnum-1]))[0][0],:]
        data,data_close,data_open,data_high,data_low,data_volume,price_list=handle_price_data(instrument,lookforwardperiod,2)
        indicator = methoddict[tmpmtd](data, int(np.nan_to_num(result_high.loc[instrument][0])))
        testresult1 = test_sample_high(indicator, data_close, data_high, data_low, price_list, lookforwardperiod, testresult1)
        indicator = methoddict[tmpmtd](data, int(np.nan_to_num(result_high.loc[instrument][0])))
        testresult2 = test_sample_low(indicator, data_close, data_high, data_low, price_list, lookforwardperiod, testresult2)
    result_high['test_absdiff'] = testresult1[:,0]
    result_high['test_reldiff'] = testresult1[:,1]
    result_low['test_absdiff'] = testresult2[:,0]
    result_low['test_reldiff'] = testresult2[:,1]
    result_high['type'] = 1
    result_low['type'] = -1
    result = pd.concat([result_high, result_low])
    result.to_csv(tmpmtd+'.csv')


# In[ ]:


def PSYMA(data, n1, n2):
    close,openp,high,low,vol = data_to_price(data)
    tmp = ((np.array([0]+list(np.diff(close))))>0) * 1.0
    return talib.SMA(np.nan_to_num(talib.SMA(tmp,n1)*100), n2)

def DMA_DDD(data, n1, n2):
    close,openp,high,low,vol = data_to_price(data)
    return np.nan_to_num(talib.SMA(close, n1) - talib.SMA(close, n2))

def CRMA(data, n1, n2):
    close,openp,high,low,vol = data_to_price(data)
    mid = (high + low + close)/3
    cr = talib.SMA(np.maximum(0, high-np.roll(mid,1)),n1) / talib.SMA(np.maximum(0, np.roll(mid,1)-low),n1) * 100
    cr = np.nan_to_num(cr)
    return np.roll(talib.SMA(cr, n2),int(n2/2.5+1))

def ZDZB(data, n1, n2):
    close,openp,high,low,vol = data_to_price(data)
    pricediff = np.array([0]+list(diff(close)))
    pricediff_pos = pricediff.copy()
    pricediff_pos[pricediff_pos<0] = 0
    pricediff_neg = pricediff.copy()
    pricediff_neg[pricediff_neg>0] = 0
    a = talib.SMA(pricediff_pos,n1) / np.abs(talib.SMA(pricediff_neg,n1))
    return talib.SMA(np.nan_to_num(a), n2)

method = ['心理线-psyma','平均线差dma-ddd','CR能量指标-crma','筑底指标-zbzd']
methoddict = {'心理线-psyma':PSYMA,'平均线差dma-ddd':DMA_DDD,'CR能量指标-crma':CRMA,'筑底指标-zdzb':ZDZB}

for tmpmtd in method:
    print(tmpmtd)    
    result_high = pd.DataFrame(index = L, columns = ['n1', 'n2', 'absdiff', 'reldiff'])
    result_low = pd.DataFrame(index = L, columns = ['n1', 'n2', 'absdiff', 'reldiff'])
    colomnnum = result_high.shape[1]
    testresult1 = np.empty((0,2), float)
    testresult2 = np.empty((0,2), float)
    for instrument in L:
        data,data_close,data_open,data_high,data_low,data_volume,price_list=handle_price_data(instrument,lookforwardperiod,1)
        highresult = np.empty((0,colomnnum), float)
        lowresult = np.empty((0,colomnnum), float)    
        for n1 in range(2,100,1):
            for n2 in range(2,100,1):
                indicator = methoddict[tmpmtd](data, n1, n2)
                open_high,close_high,open_low,close_low = test_for_price_difference(indicator, data_close, data_high, data_low, price_list, lookbackperiod)
                if len(open_high) != 0:
                    highresult = vstack((highresult,np.array([n1, n2, np.mean(close_high-open_high), np.mean(close_high/open_high-1)])))
                if len(open_low) != 0:
                    lowresult = vstack((lowresult,np.array([n1, n2, np.mean(open_low-close_low), np.mean(open_low/close_low-1)])))
        if len(lowresult) != 0:
            result_low.loc[instrument] = lowresult[np.where(lowresult[:,colomnnum-1] == np.amin(lowresult[:,colomnnum-1]))[0][0],:]
        if len(highresult) != 0:
            result_high.loc[instrument] = highresult[np.where(highresult[:,colomnnum-1] == np.amin(highresult[:,colomnnum-1]))[0][0],:]
        data,data_close,data_open,data_high,data_low,data_volume,price_list=handle_price_data(instrument,lookforwardperiod,2)
        indicator = methoddict[tmpmtd](data, int(result_high.loc[instrument][0]), int(result_high.loc[instrument][1]))
        testresult1 = test_sample_high(indicator, data_close, data_high, data_low, price_list, lookforwardperiod, testresult1)
        indicator = methoddict[tmpmtd](data, int(result_low.loc[instrument][0]), int(result_low.loc[instrument][1]))
        testresult2 = test_sample_low(indicator, data_close, data_high, data_low, price_list, lookforwardperiod, testresult2)
    result_high['test_absdiff'] = testresult1[:,0]
    result_high['test_reldiff'] = testresult1[:,1]
    result_low['test_absdiff'] = testresult2[:,0]
    result_low['test_reldiff'] = testresult2[:,1]
    result_high['type'] = 1
    result_low['type'] = -1
    result = pd.concat([result_high, result_low])
    result.to_csv(tmpmtd+'.csv')


# In[ ]:


def DMA_AMA(data, n1, n2, n3):
    close,openp,high,low,vol = data_to_price(data)
    ddd = talib.SMA(close, n1) - talib.SMA(close, n2)
    ama = talib.SMA(np.nan_to_num(ddd), n3)
    return ama

def RCCD_DIF(data, n1, n2, n3):
    close,openp,high,low,vol = data_to_price(data)
    rc = close / np.roll(close, n1)
    rc = np.nan_to_num(rc)
    arc = np.zeros(len(close))
    for t in range(0,len(close)):
        arc[t] = arc[t-1]*(n1-1)/n1 + rc[t-1]*1/n1
    dif = talib.SMA(np.roll(arc, 1), n2) - talib.SMA(np.roll(arc, 1), n3)
    return np.nan_to_num(dif)

def RCCD(data, n1, n2, n3):
    close,openp,high,low,vol = data_to_price(data)
    rc = close / np.roll(close, n1)
    rc = np.nan_to_num(rc)
    arc = np.zeros(len(close))
    for t in range(0,len(close)):
        arc[t] = arc[t-1]*(n1-1)/n1 + rc[t-1]*1/n1
    dif = talib.SMA(np.roll(arc, 1), n2) - talib.SMA(np.roll(arc, 1), n3)
    dif = np.nan_to_num(dif)
    rccd = np.zeros(len(close))
    for t in range(0,len(close)):
        rccd[t] = rccd[t-1]*(n1-1)/n1 + dif[t]*1/n1
    return rccd

def MICD_DIF(data, n1, n2, n3):
    close,openp,high,low,vol = data_to_price(data)
    mi = close - np.roll(close, 1)
    ami = np.zeros(len(close))
    for t in range(0,len(close)):
        ami[t] = ami[t-1]*(n1-1)/n1 + mi[t]*1/n1
    dif = talib.SMA(np.roll(ami,1),n2) - talib.SMA(np.roll(ami,1),n3)
    return np.nan_to_num(dif)

def MICD(data, n1, n2, n3):
    close,openp,high,low,vol = data_to_price(data)
    mi = close - np.roll(close, 1)
    ami = np.zeros(len(close))
    for t in range(0,len(close)):
        ami[t] = ami[t-1]*(n1-1)/n1 + mi[t]*1/n1
    dif = talib.SMA(np.roll(ami,1),n2) - talib.SMA(np.roll(ami,1),n3)
    dif = np.nan_to_num(dif)
    micd = np.zeros(len(close))
    for t in range(0,len(close)):
        micd[t] = micd[t-1]*(10-1)/10 + dif[t]*1/10
    return micd

def DBCD(data, n1, n2, n3):
    close,openp,high,low,vol = data_to_price(data)
    bias = (close - talib.SMA(close, n1)) / talib.SMA(close, n1)
    dif = bias - roll(bias, n2)
    dif = np.nan_to_num(dif)
    dbcd = np.zeros(len(close))
    for t in range(0,len(close)):
        dbcd[t] = dbcd[t-1]*(n3-1)/n3 + dif[t]*1/n3
    return dbcd

def DBCD_MM(data, n1, n2, n3):
    close,openp,high,low,vol = data_to_price(data)
    bias = (close - talib.SMA(close, n1)) / talib.SMA(close, n1)
    dif = bias - roll(bias, n2)
    dif = np.nan_to_num(dif)
    dbcd = np.zeros(len(close))
    for t in range(0,len(close)):
        dbcd[t] = dbcd[t-1]*(n3-1)/n3 + dif[t]*1/n3
    mm = talib.SMA(dbcd, 5)
    return mm

def KDJ_K(data, n1, n2, n3):
    close,openp,high,low,vol = data_to_price(data)
    kvalue, dvalue = talib.STOCH(high, low, close, n1, n2, 0, n3, 0)
    return kvalue

def KDJ_D(data, n1, n2, n3):
    close,openp,high,low,vol = data_to_price(data)
    kvalue, dvalue = talib.STOCH(high, low, close, n1, n2, 0, n3, 0)
    return dvalue

def KDJ_J(data, n1, n2, n3):
    close,openp,high,low,vol = data_to_price(data)
    kvalue, dvalue = talib.STOCH(high, low, close, n1, n2, 0, n3, 0)
    return 3 * kvalue - 2 * dvalue

def MACD_DIFF(data, n1, n2, n3):
    close,openp,high,low,vol = data_to_price(data)
    macd, macdsignal, macdhist = talib.MACD(close, n1, n2, n3)
    return macd

def MACD_DEA(data, n1, n2, n3):
    close,openp,high,low,vol = data_to_price(data)
    macd, macdsignal, macdhist = talib.MACD(close, n1, n2, n3)
    return macdsignal

def MACD_HIST(data, n1, n2, n3):
    close,openp,high,low,vol = data_to_price(data)
    macd, macdsignal, macdhist = talib.MACD(close, n1, n2, n3)
    return macdhist
    
    
    
method = ['平均线差dma-ama',
          '异同离差变化率指数-rccd-dif',
          '异同离差变化率指数-rccd',
          '异同离差动力指数-micd-dif',
          '异同离差动力指数-micd',
          '异同离差乖离率-dbcd-mm',
          '异同离差乖离率-dbcd',
          '随机指标-kdj-k',
          '随机指标-kdj-d',
          '随机指标-kdj-j',
          '平滑移动平均线-macd-diff',
          '平滑移动平均线-macd-dea',
          '平滑移动平均线-macd-hist']

methoddict = {'平均线差dma-ama': DMA_AMA,
              '异同离差变化率指数-rccd-dif': RCCD_DIF,
              '异同离差变化率指数-rccd':RCCD,
              '异同离差动力指数-micd-dif': MICD_DIF,
              '异同离差动力指数-micd':MICD,
              '异同离差乖离率-dbcd-mm':DBCD_MM,
              '异同离差乖离率-dbcd': DBCD,
              '随机指标-kdj-k': KDJ_K,
              '随机指标-kdj-d': KDJ_D,
              '随机指标-kdj-j': KDJ_J,
              '平滑移动平均线-macd-diff': MACD_DIFF,
              '平滑移动平均线-macd-dea': MACD_DEA,
              '平滑移动平均线-macd-hist': MACD_HIST}


method = ['随机指标-kdj-k', '随机指标-kdj-d']
methoddict = {'随机指标-kdj-k': KDJ_K, '随机指标-kdj-d': KDJ_D}


for tmpmtd in method:
    print(tmpmtd)    
    result_high = pd.DataFrame(index = L, columns = ['n1', 'n2', 'n3', 'absdiff', 'reldiff'])
    result_low = pd.DataFrame(index = L, columns = ['n1', 'n2', 'n3', 'absdiff', 'reldiff'])
    colomnnum = result_high.shape[1]
    testresult1 = np.empty((0,2), float)
    testresult2 = np.empty((0,2), float)
    for instrument in L:
        data, data_close, data_open, data_high, data_low, data_volume, price_list = handle_price_data(instrument, lookforwardperiod, 1)
        highresult = np.empty((0,colomnnum), float)
        lowresult = np.empty((0,colomnnum), float)    
        for n1 in range(2,100,2):
            for n2 in range(2,100,2):
                for n3 in range(2,100,2):
                    indicator = methoddict[tmpmtd](data, n1, n2, n3)
                    open_high,close_high,open_low,close_low = test_for_price_difference(indicator, data_close, data_high, data_low, price_list, lookbackperiod)
                    if len(open_high) != 0:
                        highresult = vstack((highresult,np.array([n1, n2, n3, np.mean(close_high-open_high), np.mean(close_high/open_high-1)])))
                    if len(open_low) != 0:
                        lowresult = vstack((lowresult,np.array([n1, n2, n3, np.mean(open_low-close_low), np.mean(open_low/close_low-1)])))
        if len(lowresult) != 0:
            result_low.loc[instrument] = lowresult[np.where(lowresult[:,colomnnum-1] == np.amin(lowresult[:,colomnnum-1]))[0][0],:]
        if len(highresult) != 0:
            result_high.loc[instrument] = highresult[np.where(highresult[:,colomnnum-1] == np.amin(highresult[:,colomnnum-1]))[0][0],:]
        data,data_close,data_open,data_high,data_low,data_volume,price_list=handle_price_data(instrument,lookforwardperiod,2)
        indicator = methoddict[tmpmtd](data, int(result_high.loc[instrument][0]), int(result_high.loc[instrument][1]),int(result_high.loc[instrument][2]))
        testresult1 = test_sample_high(indicator, data_close, data_high, data_low, price_list, lookforwardperiod, testresult1)
        indicator = methoddict[tmpmtd](data, int(result_low.loc[instrument][0]), int(result_low.loc[instrument][1]), int(result_high.loc[instrument][2]))
        testresult2 = test_sample_low(indicator, data_close, data_high, data_low, price_list, lookforwardperiod, testresult2)
    result_high['test_absdiff'] = testresult1[:, 0]
    result_high['test_reldiff'] = testresult1[:, 1]
    result_low['test_absdiff'] = testresult2[:, 0]
    result_low['test_reldiff'] = testresult2[:, 1]
    result_high['type'] = 1
    result_low['type'] = -1
    result = pd.concat([result_high, result_low])
    result.to_csv(tmpmtd+'.csv')


def SMA(data, n, m):
    sma = np.zeros(len(data))
    for t in range(0,len(data)):
        sma[t] = sma[t-1] * (n-m)/n + data[t] * m/n
    return sma


def EMA(data, n):
    ema = np.zeros(len(data))
    for t in range(0,len(data)):
        ema[t] = 2*data[t]/(n+1)+(n-1)*ema[t-1]/(n+1)
    return ema


def REF(data, n):
    return np.roll(data, n)


def KDJ_D(data, n1, n2, n3):
    close,openp,high,low,vol = data_to_price(data)
    kvalue, dvalue = talib.STOCH(high, low, close, n1, n2, 0, n3, 0)
    return dvalue


def SLOWKD_D(data, n1, n2, n3, n4):
    close,openp,high,low,vol = data_to_price(data)
    k = KDJ_D(data, n1, n2, n3)
    k = np.nan_to_num(k)
    d = SMA(k, n4, 1)
    return d

method = ['SLOWKD_D']
methoddict = {'SLOWKD_D':SLOWKD_D}

for tmpmtd in method:
    print(tmpmtd)    
    result_high = pd.DataFrame(index = L, columns = ['n1', 'n2', 'n3', 'n4', 'absdiff', 'reldiff'])
    result_low = pd.DataFrame(index = L, columns = ['n1', 'n2', 'n3', 'n4', 'absdiff', 'reldiff'])
    colomnnum = result_high.shape[1]
    testresult1 = np.empty((0,2), float)
    testresult2 = np.empty((0,2), float)
    for instrument in L:
        data,data_close,data_open,data_high,data_low,data_volume,price_list=handle_price_data(instrument,lookforwardperiod,1)
        highresult = np.empty((0,colomnnum), float)
        lowresult = np.empty((0,colomnnum), float)    
        for n1 in range(2,100,2):
            for n2 in range(2,50,2):
                for n3 in range(2,50,2):
                    for n4 in range(2,50,2):
                        indicator = methoddict[tmpmtd](data, n1, n2, n3, n4)
                        open_high,close_high,open_low,close_low = test_for_price_difference(indicator, data_close, data_high, data_low, price_list, lookbackperiod)
                        if len(open_high) != 0:
                            highresult = vstack((highresult,np.array([n1, n2, n3, n4, np.mean(close_high-open_high), np.mean(close_high/open_high-1)])))
                        if len(open_low) != 0:
                            lowresult = vstack((lowresult,np.array([n1, n2, n3, n4, np.mean(open_low-close_low), np.mean(open_low/close_low-1)])))
        if len(lowresult) != 0:
            result_low.loc[instrument] = lowresult[np.where(lowresult[:,colomnnum-1] == np.amin(lowresult[:,colomnnum-1]))[0][0],:]
        if len(highresult) != 0:
            result_high.loc[instrument] = highresult[np.where(highresult[:,colomnnum-1] == np.amin(highresult[:,colomnnum-1]))[0][0],:]
        data,data_close,data_open,data_high,data_low,data_volume,price_list=handle_price_data(instrument,lookforwardperiod,2)
        indicator = methoddict[tmpmtd](data, int(result_high.loc[instrument][0]), int(result_high.loc[instrument][1]),int(result_high.loc[instrument][2]),int(result_high.loc[instrument][3]))
        testresult1 = test_sample_high(indicator, data_close, data_high, data_low, price_list, lookforwardperiod, testresult1)
        indicator = methoddict[tmpmtd](data, int(result_low.loc[instrument][0]), int(result_low.loc[instrument][1]), int(result_high.loc[instrument][2]),int(result_high.loc[instrument][3]))
        testresult2 = test_sample_low(indicator, data_close, data_high, data_low, price_list, lookforwardperiod, testresult2)
    result_high['test_absdiff'] = testresult1[:,0]
    result_high['test_reldiff'] = testresult1[:,1]
    result_low['test_absdiff'] = testresult2[:,0]
    result_low['test_reldiff'] = testresult2[:,1]
    result_high['type'] = 1
    result_low['type'] = -1
    result = pd.concat([result_high, result_low])
    result.to_csv(tmpmtd+'.csv')


def B3612_B36(data):
    close,openp,high,low,vol = data_to_price(data)
    b36 = talib.SMA(close, 3) - talib.SMA(close, 6)
    return b36

def B3612_B612(data):
    close,openp,high,low,vol = data_to_price(data)
    b612 = talib.SMA(close, 6) - talib.SMA(close, 12)
    return b612

def ASI(data):
    close,openp,high,low,vol = data_to_price(data)
    lc = np.roll(close,1)
    aa = np.abs(high - lc)
    bb = np.abs(low - lc)
    cc = np.abs(high - np.roll(low, 1))
    dd = np.abs(lc - np.roll(openp, 1))
    r = np.zeros(len(close))
    for t in range(0, len(close)):
        if aa[t] > bb[t] and aa[t] > cc[t]:
            r[t] = aa[t] + bb[t]/2 + dd[t]/4
        elif bb[t] > cc[t] and bb[t] > aa[t]:
            r[t] = bb[t] + aa[t]/2 + dd[t]/4
        else:
            r[t] = cc[t] + dd[t]/4
    x = close - lc + (close - openp)/2 + lc - np.roll(openp,1)
    si = 16 * x / r * np.maximum(aa, bb)
    asi = np.cumsum(si)
    return asi

def QHLSR_QHL5(data):
    close,openp,high,low,vol = data_to_price(data)
    qhl = (close - np.roll(close,1)) - (vol - np.roll(vol,1)) * (np.roll(high,1)-np.roll(low,1)) / np.roll(vol,1)
    qhl_pos = qhl.copy()
    qhl_pos[qhl_pos < 0] = 0
    a = talib.SMA(qhl_pos, 5) * 5
    qhl_neg = qhl.copy()
    qhl_neg[qhl_neg > 0] = 0
    b = np.abs(talib.SMA(qhl_neg, 5) * 5)
    d = a / (a+b)
    qhl_pos2 = (qhl>0) * 1.0
    qhl_neg2 = (qhl<0) * 1.0
    qhl_posma = talib.SMA(qhl_pos2, 5) * 5
    qhl_negma = talib.SMA(qhl_neg2, 5) * 5
    qhl5 = np.zeros(len(close))
    for t in range(0,len(close)):
        if qhl_posma[t] == 5:
            qhl5[t] = 1
        elif qhl_negma[t] == 5:
            qhl5[t] = 0
        else:
            qhl5[t] = d[t]
    return qhl5


def QHLSR_QHL10(data):
    close,openp,high,low,vol = data_to_price(data)
    qhl = (close - np.roll(close,1)) - (vol - np.roll(vol,1)) * (np.roll(high,1)-np.roll(low,1)) / np.roll(vol,1)
    qhl_pos = qhl.copy()
    qhl_pos[qhl_pos < 0] = 0
    e = talib.SMA(qhl_pos, 10) * 10
    qhl_neg = qhl.copy()
    qhl_neg[qhl_neg > 0] = 0
    f = np.abs(talib.SMA(qhl_neg, 10) * 10)
    g = e / (e+f)
    return g

def LONG(data):
    close,openp,high,low,vol = data_to_price(data)
    tb = np.zeros(len(close))
    ts = np.zeros(len(close))
    for t in range(0,len(close)):
        if high[t] > close[t-1]:
            tb[t] = high[t] - close[t-1] + close[t] - low[t]
        else:
            tb[t] = close[t] - low[t]
        if close[t-1] > low[t]:
            ts[t] = close[t-1] - low[t] + high[t] - close[t]
        else:
            ts[t] = high[t] - close[t]
    vol1 = (tb-ts)*vol/(tb+ts)/10000
    vol10 = np.zeros(len(close))
    vol11 = np.zeros(len(close))
    for t in range(1,len(close)):
        vol10[t] = vol10[t-1]*(1-0.1)+vol1[t]*0.1
        vol11[t] = vol11[t-1]*(1-0.05)+vol1[t]*0.05
    return np.cumsum(vol10-vol11)

def SHORT(data):
    close,openp,high,low,vol = data_to_price(data)
    tb = np.zeros(len(close))
    ts = np.zeros(len(close))
    for t in range(0,len(close)):
        if high[t] > close[t-1]:
            tb[t] = high[t] - close[t-1] + close[t] - low[t]
        else:
            tb[t] = close[t] - low[t]
        if close[t-1] > low[t]:
            ts[t] = close[t-1] - low[t] + high[t] - close[t]
        else:
            ts[t] = high[t] - close[t]
    vol1 = (tb-ts)*vol/(tb+ts)/10000
    vol10 = np.zeros(len(close))
    vol11 = np.zeros(len(close))
    for t in range(1,len(close)):
        vol10[t] = vol10[t-1]*(1-0.1)+vol1[t]*0.1
        vol11[t] = vol11[t-1]*(1-0.05)+vol1[t]*0.05
    return vol10-vol11


method = ['三减六日乖离b3612-b36','三减六日乖离b3612-b612','振动升降指标-asi','阻力指标-qhlsr-qhl5',          '阻力指标-qhlsr-qhl10','长线指标-LON长线','短线指标-SHORT短线']
methoddict = {'三减六日乖离b3612-b36':B3612_B36,'三减六日乖离b3612-b612':B3612_B612,'振动升降指标-asi':ASI,              '阻力指标-qhlsr-qhl5':QHLSR_QHL5,'阻力指标-qhlsr-qhl10':QHLSR_QHL10,'长线指标-LON长线':LONG,              '短线指标-SHORT短线':SHORT}

for tmpmtd in method:
    print(tmpmtd)    
    result_high = pd.DataFrame(index = L, columns = ['absdiff', 'reldiff'])
    result_low = pd.DataFrame(index = L, columns = ['absdiff', 'reldiff'])
    colomnnum = result_high.shape[1]
    testresult1 = np.empty((0,2), float)
    testresult2 = np.empty((0,2), float)
    for instrument in L:
        data, data_close,data_open,data_high,data_low,data_volume,price_list=handle_price_data(instrument,lookforwardperiod,1)
        highresult = np.empty((0,colomnnum), float)
        lowresult = np.empty((0,colomnnum), float)    
        
        indicator = methoddict[tmpmtd](data)
        open_high,close_high,open_low,close_low = test_for_price_difference(indicator, data_close, data_high, data_low, price_list, lookbackperiod)
        if len(open_low) != 0:
            result_low.loc[instrument] = np.array([np.mean(open_low-close_low), np.mean(open_low/close_low-1)])
        if len(open_high) != 0:
            result_high.loc[instrument] = np.array([np.mean(close_high-open_high), np.mean(close_high/open_high-1)])
        data,data_close,data_open,data_high,data_low,data_volume,price_list=handle_price_data(instrument,lookforwardperiod,2)
        indicator = methoddict[tmpmtd](data)
        testresult1 = test_sample_high(indicator, data_close, data_high, data_low, price_list, lookforwardperiod, testresult1)
        indicator = methoddict[tmpmtd](data)
        testresult2 = test_sample_low(indicator, data_close, data_high, data_low, price_list, lookforwardperiod, testresult2)
    result_high['test_absdiff'] = testresult1[:,0]
    result_high['test_reldiff'] = testresult1[:,1]
    result_low['test_absdiff'] = testresult2[:,0]
    result_low['test_reldiff'] = testresult2[:,1]
    result_high['type'] = 1
    result_low['type'] = -1
    result = pd.concat([result_high, result_low])
    result.to_csv(tmpmtd+'.csv')
